"Initializes the external view by obtaining the subview denoted by the parameter: anArray having the form #(className selectorOrMessage). The external view's inset window and the subview's viewport must be made to correspond. Two solutions are possible: (1) make the external view's inset window the same as the subview's viewport or (2) make the subview's viewport the same as the external view's inset window. Solution (1) is used here. This leaves the subview unaffected."
"Since the borders in the containing view do not actually scale, this view (if left unchanged) will be positioned at a point that assumes the borders did scale. This can be eliminated by transforming into the inset display box rather than the display box. See View | computeDisplayTransformation for the difference."
"Since the borders in the containing view do not actually scale, this view (if left unchanged) will be positioned at a point that assumes the borders did scale. This can be eliminated by transforming into the inset display box rather than the display box. See View | computeDisplayTransformation for the difference."
"Since the borders in the containing view do not actually scale, this view (if left unchanged) will be positioned at a point that assumes the borders did scale. This can be eliminated by transforming into the inset display box rather than the display box. See View | computeDisplayTransformation for the difference."
"Store this ExtendedStandardSystemView using indentation for readability. Either generates the encoding or uses the one provided if aStringOrNil is non-nil. Only generates the subviews if aBoolean is true."
| return continue |
return _ (WriteStream on: (String new: 16)) crtab: indentation; contents.
^self error: 'method too large -- cannot be compiled. Continue to give up']!
compileOneOrMoreMethods: view intoClass: class method: methodName category: categoryName overFlowCategory: overflowCategoryName
"Attempts to compile one method in the specified class that re-creates the view. If it is too large to compile, breaks it up by creating additional overflow methods with suffixes 'Continue1:', 'Continue2:', ... that add the subviews. These overflow methods are placed in category overflowCategoryName."
| aStream source |
"Create the method."
Transcript show: ' method 1'.
aStream _ WriteStream on: (String new: 10000).
aStream
nextPutAll: methodName; crtab;
nextPutAll: '"Returns an initialized view."'; crtab;
nextPut: $^; store: view.
"Compile it."
source _ aStream contents. aStream _ nil.
(self tryCompiling: source class: class classified: categoryName)
^self compileTwoOrMoreMethods: view intoClass: class
method: methodName category: categoryName
overFlowCategory: overflowCategoryName]!
compileTwoOrMoreMethods: view intoClass: class method: methodName category: categoryName overFlowCategory: overflowCategoryName
"Compile the view in pieces where the encoding is considered one piece (piece -1), the top view is considered another piece (piece 0), and the individual subviews are pieces (1, 2, 3, ...). Attempt to put at many pieces into each method as the compiler will permit. The first method with name methodName is place in category categoryName. The overflow methods have suffixes 'Continue1:', 'Continue2:', ... appended to the method name. They are placed in category overflowCategoryName."
| lastPiece limit continuation mostPieces fewestPieces pieces next |
"Iterate to create the maximal sized compiled method."
removeContinuationsStartingAt: start for: methodName class: class
| index selector |
index _ start. selector _ self continuationName: index for: methodName.
[class includesSelector: selector] whileTrue: [
class removeSelector: selector.
index _ index + 1.
selector _ self continuationName: index for: methodName]!
tryCompiling: aMethodString class: class classified: aCategoryString
"Returns true if compilation is successful; false otherwise. Note: this method is invoked rather than executing the code inline to force compiler data structures to disappear (it only happens when a return from compile:classified:notifying: occurs or the error block is executed)."
| notifier |
notifier _ ErrorHandler new errorBlock: [:message :position | ^false].
class compile: aMethodString classified: aCategoryString notifying: notifier.
"Compiles a method with with name methodName (for continuationIndex 0) and suffixes 'Continue1:', 'Continue2:', .... for (continuationIndex > 0). Piece -1 is interpreted as the encoding, piece 0 is the top view, and pieces 1, 2, 3, ... are the subviews. No additional overflow methods are generated if overflowCategoryName is nil."
'Provides either a constant- (the default) or varying-sized view for displaying the switch labels. The first is meant for labels that don''t scale; the second for labels that do. The second also permits a switch label that doesn''t scale to be displayed in a varying-sized area. An example of an object that scales is a form; an example of one that doesn''t is a string converted to a paragraph or a display text. Constant-sized views have display boxes that are the same size as the window. There is no such correlation for varying-sized views.
To better explain the two varieties, suppose an extended switch view''s label size is 10-by-10. Also, the view''s window of size 50@50 would under normal circumstances transform to a display box of size 100@100. Let''s call this display box -- the expected display box. Three cases are possible:
1. constant-size view => the actual display box ends up being 50-by-50. Where it is actually positioned will depends on a specified fixed point (discussed below).
2. varying-size view and a label that doesn''t scale => the actual display box is the expected display box of size 100@100 but the label (unscaled) can be positioned anywhere inside; again, this is specified via a fixed point.
3. varying-size view and a label that scales => the actual display box is the expected display box of size 100@100 and the label is scaled to fit exactly.
Fixed points are used to specify which part of the view''s window is to be transformed unaltered. When the fixed point is inside the window, self relative positioning is obtained. When it is outside, more global positioning permits rows or columns of views to be made adjacent. For example, methods fixTopLeftCorner, fixCenter, and fixBottomRightCorner cause the 50-by-50 window mentioned above to be positioned at the top left, center, and bottom right respectively of the expected display box (inside positioning). Methods fixInHorizontalBankAtPosition: and fixInVerticalBankAtPosition: cause the 50-by-50 window to be positioned in a row or column respectively (the row or column index is a parameter).
Users can also provide a highlight object and specify whether or not it is to be overlayed over the label as opposed to replacing it when the switch is depressed (the default is to replace). If no highlight object is provided, highlighting is perform in the standard way (using reverse video).
Additionally, the view permits an arbitrary change/update symbol called the aspect symbol to be specified. By contrast, switch views use the selector as the aspect symbol.
Finally, both the view''s ''isOn'' selector and the controller''s ''switch'' selector can be blocks with two parameters: model, view.
OLDER VERSION:
Provides either a constant- (the default) or varying-sized view for displaying the switch labels. The first is meant for labels that don''t scale; the second for labels that do. The second also permits a switch label that doesn''t scale to be displayed in a varying-sized area. An example of an object that scales is a form; an example of one that doesn''t is a string converted to a paragraph or a display text.
To better explain the two varieties, suppose an extended switch view''s label size is 10-by-10 but the view''s window would under normal circumstances transform to a display box of size 50@50. Let''s call this display box -- the expected display box. Three cases are possible:
1. constant-size view => the actual display box ends up being 10-by-10 plus the border size. Where it actually ends up will depends on a specified fixed point (discussed below).
2. varying-size view and a label that doesn''t scale => the actual display box is the expected display box of size 50@50 but the label (unscaled) can be positioned anywhere inside; again, this is specified via a fixed point.
3. varying-size view and a label that scales => the actual display box is the expected display box of size 50@50 and the label is scaled to fit exactly.
Fixed points are used to specify which part of the view''s window is to be transformed unaltered. When the fixed point is inside the window, self relative positioning is obtained. When it is outside, more global positioning permits rows or columns of views to be made adjacent. For example, methods fixTopLeftCorner, fixCenter, and fixBottomRightCorner cause the 10-by-10 label mentioned above to be positioned at the top left, center, and bottom right respectively of the expected display box (inside positioning). Methods fixInHorizontalBankAtPosition: and fixInVerticalBankAtPosition: cause the 10-by-10 label to be positioned in a row or column respectively (the row or column index is a parameter).
Users can also provide a highlight object and specify whether or not it is to be overlayed over the label as opposed to replacing it when the switch is depressed (the default is to replace). If no highlight object is provided, highlighting is perform in the standard way (using reverse video).
Additionally, the view permits an arbitrary change/update symbol called the aspect symbol to be specified. By contrast, switch views use the selector as the aspect symbol.
Finally, both the view''s ''isOn'' selector and the controller''s ''switch'' selector can be blocks with two parameters: model, view.'!
"For varying-size switches, the default computeDisplayTransformation is used. For constant-size switches, additional computation is required. First, the default display transformation is computed and then used to determine where the fixed point should be displayed. Then a new display transformation with no scaling is constructed which translates the label origin in such a way that the fixed point is at the position determined above. Note that the resulting display box is consequently the same size as the window (not necessarily the same size as the label)."
"Displays the view taking into account the status of the model, the label, and the highlight object. To present an instantaneous picture, the view is first internally displayed on a form."
| aForm displayBox |
"Take the inside color into account when obtaining the form."
"Since the borders in the containing view do not actually scale, this view (if left unchanged) will be positioned at a point that assumes the borders did scale. This can be eliminated by transforming into the inset display box rather than the display box. See View | computeDisplayTransformation for the difference."
"The given display transformation is designed to transform the window (which may be located anywhere) to the display box. Returns the transformation needed to transform the label into the center of the same display box."
switchOffsets _ switchOffsets copyFrom: 1 to: switchOffsets size - 1. "remove last entry"
"Create 5 vertical banks of switches: the first four constant-size, the last varying-size. Use the same switches and labels to create five columns differing only in position and scaling."
"Add some additional transparent subviews just to provide the grid so we can better see what happened. Note: this will have to be removed since it prevents the switch views from getting control."
0.0 to: 0.8 by: 0.2 do: [:anXOffset |
switchOffsets do: [:aYOffset |
topView addSubView: View new in: (anXOffset@aYOffset extent: 0.2@switchHeight) borderWidth: 1]].
switchOffsets _ switchOffsets copyFrom: 1 to: switchOffsets size - 1. "remove last entry"
"Create 5 vertical banks of switches: the first four unscaled, the last scaled. Use the same switches and labels to create five columns differing only in position and scaling."
"Add some unnecessary transparent subviews just to provide the grid so we can better see what happened."
0.0 to: 0.8 by: 0.2 do: [:anXOffset |
switchOffsets do: [:aYOffset |
topView addSubView: View new in: (anXOffset@aYOffset extent: 0.2@switchHeight) borderWidth: 1]].
"Turn on the 2nd switch."
(switches at: 2) turnOn. "Note: causes spurious switches to be displayed since the top controller is not yet opened."
topView controller open!
example3
"Mixes forms and paragraphs. Since they are no longer identical in size, some differences will be apparent. Also, note that the fixed points have no effect in varying mode."
switchOffsets _ 0.0 to: 1.0-(switchHeight/10.0) by: switchHeight.
"Create 8 vertical banks of switches: the first four unscaled, the last four scaled. Use the same switches and labels to create eight columns differing only in position and scaling."
!ExtendedPictureView class methodsFor: 'instance creation'!
on: anObject aspect: aSymbol label: aDisplayObjectOrNil getLabel: getLabelMessageOrNil
"If the 'get label' message is nil, the supplied label is displayed (nil results in a picture with the view's inside color and border color). Otherwise, the 'get label' message is sent to the model to obtain the current label."
"Since the borders in the containing view do not actually scale, this view (if left unchanged) will be positioned at a point that assumes the borders did scale. This can be eliminated by transforming into the inset display box rather than the display box. See View | computeDisplayTransformation for the difference."
"Since the borders in the containing view do not actually scale, this view (if left unchanged) will be positioned at a point that assumes the borders did scale. This can be eliminated by transforming into the inset display box rather than the display box. See View | computeDisplayTransformation for the difference."
"Store this ExtendedStandardSystemView using indentation for readability. Either generates the encoding or uses the one provided if aStringOrNil is non-nil. Only generates the subviews if aBoolean is true."
| return continue |
return _ (WriteStream on: (String new: 16)) crtab: indentation; contents.
labels: 'create white off- and on-forms\create off- and on-forms by copying selection\copy off-form to on-form\copy on-form to off-form\delete off- and on-forms\edit off-form\edit on-form' withCRs
!FormLibrarian methodsFor: 'libraries window menu messages support'!
newLibraryNameAndIfNone: aBlock
"Returns a name for a new library; an empty string indicates cancellation. If this name is already in use, reports the problem and repeats the process unless the user elects to quit (in this case, returns the result of executing the block)."
| request newName oldName |
oldName _ 'unusedName'.
request _ [
oldName _ FillInTheBlank
request: 'Specify a name for the new library'
initialAnswer: oldName.
oldName size = 0 ifTrue: [^aBlock value "cancel requested"].
oldName].
[libraries includesKey: (newName _ request value asSymbol)] whileTrue: [
(self confirm: 'You will be prompted with the form name\and then for the size of the form to be used.\Continue?' withCRs) ifFalse: [^nil].
newName _ self newFormNameAndIfNone: [^nil].
(self confirm: 'The form size can be specified as a point or interactively.\The interactive approach is less accurate.\Do you wish to specify it as a point?' withCRs)
!FormLibrarian methodsFor: 'library window menu messages support'!
newFormNameAndIfNone: aBlock
"Returns a name for a new form; an empty string indicates cancellation. If this name is already in use, reports the problem and repeats the process unless the user elects to quit (in this case, returns the result of executing the block)."
| request newName oldName |
oldName _ 'unusedName'.
request _ [
oldName _ FillInTheBlank
request: 'Specify a name for the new form'
initialAnswer: oldName.
oldName size = 0 ifTrue: [^aBlock value "cancel requested"].
oldName].
[library includesKey: (newName _ request value asSymbol)] whileTrue: [